use std::error;
use std::error::Error;
use std::fmt;
use std::fmt::Formatter;

type Result<T> = std::result::Result<T, Box<dyn error::Error>>;

#[derive(Debug)]
struct EmptyVec;

impl fmt::Display for EmptyVec {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "invalid first item to double")
    }
}
impl error::Error for EmptyVec {
    fn description(&self) -> &str {
        "invalid first item to double"
    }
    fn cause(&self) -> Option<&dyn Error> {
        None
    }
}
fn double_first(vec: Vec<&str>) -> Result<i32> {
    let first = vec.first().ok_or(EmptyVec)?;
    let parsed = first.parse::<i32>()?;
    Ok(2 * parsed)
}

fn main() {
    println!("Hello, world!");
    let numbers = vec!["34", "43"];
    let empty = vec![];
    let strings = vec!["tofu", "45"];

    print(double_first(numbers));
    print(double_first(empty));
    print(double_first(strings));
}

fn print(result: Result<i32>) {
    match result {
        Ok(i) => println!("the first double is {}", i),
        Err(e) => println!("Error: {}", e),
    }
}
